﻿#pragma once
#include "Common/Timer/TimerAxis.h"
#include "Common/Event/Event.h"
#include "IDuplicate.h"
#include "Duplicate/star/DupStar.h"
#include "Duplicate/block/Block.h"

class Duplicate : public IDuplicate, public ITimerHandler ,public IEventExecuteSink
{
protected:
	enum
	{
		ETimer_Update = 1,		//更新定时�?
		ETimer_Relive = 2,		//死亡复活定时�?
		ETimer_Flop = 3,		//翻牌定时�?
		ETimer_Clean = 4,		//清理定时�?
		ETimer_Destory = 5,		//销毁定时器
		ETimer_StartBrush = 6,	//开始刷怪定时器（多人副本需要）
		ETimer_StartDup = 7,	//开始副本
		ETimer_UnionActivity = 8,//工会活动
		EMaxReadyStateSec = 120,	//副本准备状态的最大时间（单位：秒)
	};
public:
	///////////////////////////  ITimerHandler  ///////////////////////////////////////////////
	virtual void OnTimer(uint32_t nTimerID);
	///////////////////////////// IEventExecuteSink /////////////////////////////////////////////
	virtual void OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen);
	///////////////////////////  IDuplicate  ///////////////////////////////////////////////
	//初始�?
	virtual bool Init(uint32_t nDuplicateID, uint32_t nSceneID, IBrushMonster *pBrush);
	//
	virtual void UnInit();
	//获取副本ID
	virtual uint32_t GetDuplicateID();
	//获取场景ID
	virtual uint32_t GetSceneID();
	//获取地图ID
	virtual uint32_t GetMapID();
	//获取开始时间
	virtual uint64_t GetStartTime();
	//获取刷怪类�?370109902
	virtual int8_t GetType();
	//获取副本额外参数
	virtual DExParam &GetExParam();
	//获取副本配置信息
	virtual const DuplicateDuplicateCfgInfo *GetDuplicateCfgInfo();
	//是否能进�?
	virtual bool CanEnter(Creature *pCreature);
	//进入副本
	virtual bool EnterDuplicate(Creature *pCreature, Point3<float> &pos);
	//离开副本
	virtual int32_t LeaveDuplicate(Player *pPlayer,bool retMainCity = false);
	//复活（已废弃）
	virtual bool Relive(Player *pPlayer, int8_t byType);
	//是否能复活
	virtual bool CanRelive(CharIDType charId);
	//复活
	virtual bool Relive(Player *pPlayer);
	//是否刷怪完�?
	virtual bool FinishBrush();
	//是否处于抽奖状�?
	virtual bool IsFlopState();
	//是否结束
	virtual bool IsEnd();
	//获取刷怪数�?
	virtual AllBrushDataCfg *GetBrushData() { return &m_brushCfg; };
	//初始化脚�?
	virtual bool InitScript();
	//进入区域
	virtual bool EnterArea(uint32_t nAreaID);
	//开始刷第几波怪物�?
	virtual void StartBrushWave(int32_t wave);
	//获取玩家复活次数
	virtual int32_t PlayerReliveNum(CharIDType cid);
	//玩家是否曾经进入副本
	virtual bool OnceEnter(CharIDType cid);
	//设置玩家是否可获得奖�?
	virtual void SetCanReward(CharIDType cid, bool canReward);
	//获取玩家是否可获得奖�?
	virtual bool CanReward(CharIDType cid);
	//获取死亡怪物数量
	virtual uint32_t GetDieMonsterNum(uint32_t monsterId);
	//获取额外的死亡怪怪物数量
	virtual uint32_t GetDieMonsterNumExcept(SET_UINT32 &setExcept);
	//获取怪物剩余数量
	virtual int32_t GetMonsterNum();
	//获取指定怪物类型序列剩余数量
	virtual int32_t GetMonsterNum(SET_INT32 &setType);
	//获取指定怪物ID的剩余数量
	virtual int32_t GetMonsterLeftNum(uint32_t monsterId);
	//获取指定怪物ID的总数量
	virtual int32_t GetMonsterTotalNum(uint32_t monsterId);
	//开始刷�?
	virtual uint64_t StartBrushTime();
	//获取副本剩余时间
	virtual int32_t LeftSec();
	//获取塔的信息
	virtual void GetTowerInfo(uint64_t &curHp, uint64_t &maxHp);
	//获取以传送的怪物数量
	virtual int32_t GetTransNum();
	//获取玩家进入之前的区�?
	virtual uint32_t GetBeforeArea(CharIDType charId);
	//副本场景广播
	virtual void BroadCastData(uint16_t moduleId, uint16_t cmdId, ProtoBufBase *pbuf);
	//获取星级状�?
	virtual int8_t GetStartState(MAP_INT8_INT8 &mapState);
	//工会解散
	virtual void UnionDismiss(){};
	//踢出玩家
	virtual void KickPlayer(CharIDType charId) {};
	//是否能使用药�?
	virtual bool CanUseItem() { return true; };
	//开始挑�?
	virtual int32_t StartChallenge(CharIDType charId) { return RET_FAIL; };
	//获取功勋
	virtual int32_t GetExploit(CharIDType charId) { return 0; };
	//购买功勋商店物品  costExploit : 购买物品需要消耗的功勋
	virtual void BuyExploitItem(CharIDType charId, int32_t costExploit) {};
	//获取瘟疫之战�?感染者和生还者数�?
	virtual void GetPestilenceNum(int32_t &injectNum, int32_t &surviveNum){};
	//获取瘟疫之战持续时间和变身ID
	virtual void GetPestilenceContiAndTransID(int32_t &contiSec, int32_t &injectTransId, int32_t &surviveTransId){};
	//获取玩家阵营
	virtual int8_t GetDupCharCamp(CharIDType charId) { return EDupCampType_None; };
	//获取阻挡配置
	virtual AllBlockDataCfg *GetBlockCfg() { return &m_blockCfg; };
	//获取阻挡状�?
	virtual void GetBlockState(MAP_UINT32_INT8 &mapBlockState);
	//活动状�?
	virtual void ActivityState(uint32_t actId,int32_t state, SUnionActParam &param){};
	//工会驻地场景创建
	virtual void BindUnionHome() {};
	//工会等级更新
	virtual void UnionLevel(int32_t unionLev) { m_paramEx.unionLev = unionLev; };
	//NPC对话
	virtual int32_t NpcTalk(CharIDType charId, uint32_t activityId, uint64_t npcCid, int32_t reply,int8_t &type){ return RET_FAIL; };
	//工会精英平均等级
	virtual int32_t UnionAverageLev() { return 0; };
	//工会首领外观
	virtual void UnionLeaderFacade(CharOutward *pNpcFacade){};
	//是否脚本刷出的怪物全部死亡
	virtual bool IsBrushMonsAllDie();
	//工会地宫关闭
	virtual void UnionDungeonClose() {};
	//离开队伍
	virtual void LeaveTeam(CharIDType charId);
	//离开房间
	virtual void LeaveRoom(CharIDType charId);
	//重连数据
	virtual void OnReconnect(CharIDType cid);
	//获取指定怪物组的怪物
	virtual void GetMonsByGroup(SET_INT32 &setGroup, MAP_UINT32_SET_UINT64 &mapGroupMons);
	//积分怪物死亡
	virtual void ScoreMonsDie(uint32_t monsId, int32_t count, int8_t byBoss, uint64_t killerCid) {};
	//拾取掉落
	virtual void PickDrop(CharIDType cid, string &strName, int32_t prof, int32_t sex, VEC_ITEM_PROTO_EX &vecPickDrop) {};
	//设置副本掉落数据
	virtual void SetDropData(DupAllDropProto &protoData) {};
	//获取新手引导当前的步骤索引
	virtual int32_t GetCurGuideIdx() { return -1; };
protected:
	//初始化副本状�?
	virtual void InitDuplicateState();
	//生物进入场景
	virtual void OnCreatureEnter(Creature *pCreature) {}
	//生物离开场景
	virtual void OnCreatureLeave(Creature *pCreature) {}
	//生物离开副本
	virtual void OnPlayerLeave(Player *pPlayer) {}
	//复活
	virtual void OnRelive(Player *pPlayer, int8_t byType) {};
	//是否能进�?
	virtual bool OnCanEnter(Creature *pCreature) { return true; };
	//进入区域
	virtual bool OnEnterArea(uint32_t nAreaID) { return true; };
	//下线
	virtual void PlayerLogoutGame(CharIDType charId);
	//玩家离开副本
	virtual void PlayerLeave(CharIDType cid);
	//主动离开副本之前 的处理
	virtual void OnActiveBeforeLeave(CharIDType cid);
	//主动离开副本失败 的处理 
	virtual void OnActiveLeaveFaild(CharIDType cid) {};
	//进入副本成功
	virtual void OnEnterSuccess(CharIDType charId){};
	//通知玩家副本完成
	virtual void OnNotifyFinish(CharIDType charId, DuplicateResult &result){};

	//获取场景玩家
	Player *GetPlayer(CharIDType pcid);
	//删除玩家
	void DelPlayer(CharIDType cid);
	//获取场景玩家数量
	uint32_t GetPlayerCount();
	//获取场景怪物
	Monster *GetMonster(CharIDType mcid);
	//获取场景NPC
	Npc *GetNpc(CharIDType ncid);
	//获取机器�?
	CRebot *GetRobot(CharIDType rcid);
	//生物死亡
	void CreatureDead(int8_t byKind, DieEvent *pDieEvent);
	//生物攻击受击
	void CreatureAtkAndUnderAtk(skillAttackEvent *pEventAtk);
	//生物进入副本
	void CreatureEnter(EnterSceneEvent *pEnterEvent);
	//生物离开
	void CreatureLeave(LeaveSceneEvent *pLeaveEvent,uint8_t bySrcType);

	//通过怪物组增加怪物
	void AddMonsByGroup(CharIDType monsCid, int32_t formationId);
	//通过副本组移除怪物
	void DelMonsByGroup(CharIDType monsCid, int32_t formationId);

	//复活超时
	void ReliveTimeOut(CharIDType cid);
	//玩家死亡次数
	uint32_t GetPlayerDieNum(CharIDType cid);
	//增加玩家死亡次数
	void AddPlayerDieNum(CharIDType cid);
	//玩家击杀怪物数量
	uint32_t GetPlayerKillNum(CharIDType cid);
	//获取角色死亡时间
	uint64_t GetPlayerDieSec(CharIDType cid);
	//添加角色死亡时间
	void AddPlayerDieSec(CharIDType cid, uint64_t sec);
	//删除角色死亡时间
	void DelPlayerDieSec(CharIDType cid);
	//增加玩家复活次数
	void AddPlayerReliveNum(CharIDType cid);
	//塔的配置ID（怪物ID�?
	uint32_t TowerId();
	//开始刷�?
	void StartBrush();;
	//检查死亡复�?
	void CheckRelive();
	//检查副本准备状�?
	void CheckReadyState();
	//更新状�?
	void UpdateState();
	//检查是否结束-1-没结束，0-成功 1-失败
	int32_t CheckEnd();
	//检查所有怪物是否有已经达到区域
	void CheckEnterArea();
	//检查怪物出生
	void CheckMonsBorn();
	//添加出生的怪物
	void AddBornMonster(SET_UINT64 &setBorn);
	//初始化所有怪物
	void InitAllTypeMonster();
	//获取类型怪数�?
	int32_t GetMonsNumByType(int8_t monsType);
	//获取指定类型下指定怪物ID剩余数量
	int32_t GetMonsNumByType(int8_t monsType,uint32_t monsterId);
	//获取玩家输出伤害
	uint64_t GetPlayerOutput(CharIDType cid);
	//获取玩家承受伤害
	uint64_t GetPlayerBear(CharIDType cid);
	//更新玩家伤害
	void UpdatePlayerHarm(CharIDType atkSide, CharIDType bearSide, int32_t harmValue);
	//更新玩家生命
	void UpdatePlayerHp(Player *pPlayer);
	//更新玩家等级
	void UpdatePlayerLev(Player *pPlayer);
	//更新玩家信息
	void UpdatePlayerInfo(Player *pPlayer);
	//更新玩家外观
	void UpdatePlayerFacade(Player *pPlayer);
	//更新玩家在线状�?
	void UpdatePlayerOnline(Player *pPlayer,int32_t onlineState);
	//更新玩家死亡状�?
	void UpdatePlayerDie(Player *pPlayer,int32_t dieState);
	//更新副本功勋
	void UpdatePlayerExploit(Player *pPlayer,int32_t exploit);
	//获取玩家上一次的生命值
	uint32_t GetPlayerLastHp(CharIDType cid);
	//设置玩家上一次的生命值
	void SetPlayerLastHp(CharIDType cid, uint32_t hp);
	//检查玩家生命�?
	void CheckPlayerHp();
	//是否是单人副本
	bool IsSingleDup();
	//是否是多人副
	bool IsMulDup();
	//是否是房间副本
	bool IsRoomDup();
	//是否是组队副本
	bool IsTeamDup();
	//是否是云端试�?
	bool IsCloud();
	//是否是竞技场副�?
	bool IsArenaDup();
	//是否是切磋副本
	bool IsCompeteDup();
	//是否是工会驻�?
	bool IsUnionHomeDup();
	//是否是工会地宫
	bool IsUnionDungeonDup();
	//是否是瘟疫之�?
	bool IsPestilenceDup();
	//是否是天梯
	bool IsLadderDup();
	//初始化订阅事�?
	void InitCommonEvent();
	//角色进副本初始化订阅事件
	void OnPlayerEnterEvent(CharIDType charId);
	//角色离开取消订阅事件
	void OnPlayerLeaveEvent(CharIDType charId);
	//通用的副本开始状态处�?
	void OnCommon_DupBeginState();
	//通用的副本完成状态处�?
	void OnCommon_DupFinishState();
	//通用副本完成的通知处理
	void OnCommon_NotifyDupFinish(DuplicateResult &result);
	//通用的副本翻牌状态处�?
	void OnCommon_DupFlopState();
	//通用的副本清理状态处�?
	void OnCommon_DupCleanState(uint32_t sec = DUP_CLEAN_STATE_SEC);
	//通用的副本销毁状态处�?
	void OnCommon_DupDestoryState(uint32_t sec = DUP_DESTORY_STATE_SEC);

	//通用的翻牌状�?结束处理
	void OnCommon_FlopStateEnd();
	//通用的清理状�?结束处理
	void OnCommon_CleanStateEnd();
	//通用的销毁状�?结束处理
	void OnCommon_DestoryStateEnd();
	//通用的玩家离开副本处理
	bool OnCommon_PlayerLeave(CharIDType cid,bool notify = true);
	//停止怪物AI
	void OnCommon_StopMonsterAi();
	//副本完成增加阵营声望
	void OnCommon_AddPrestige();
	//初始化功�?
	void InitExploit(CharIDType charId);
	//获取功勋
	int32_t GetCharExploit(CharIDType charId);
	//增加功勋
	void AddExploit(CharIDType charId, int32_t exploit);
	//删除功勋
	void DelExploit(CharIDType charId);
	//设置活瘟疫之战动持续时间
	void SetPestilenceContiSec(int32_t sec);
	//获取瘟疫之战结果
	int8_t PestilenceWinCamp();
	//是否需要复活
	bool IsNeedRelive();
	//获取进入副本参数
	void GetEnterParam(DupEnterParam &enterParam);
protected:
	//////////////////////////  IDuplicateState ////////////////////////////////////////////////
	virtual void OnDuplicateState_Ready();
	virtual void OnDuplicateState_Begin();
	virtual void OnDuplicateState_Finish();
	virtual void OnDuplicateState_Flop();
	virtual void OnDuplicateState_Clean();
	virtual void OnDuplicateState_Destory();
	//////////////////////////////////////////////////////////////////////////

	virtual void OnReady_State() {};
	virtual void OnBegin_State() {};
	virtual void OnFinish_State() {};
	virtual void OnFlop_State() {};
	virtual void OnClean_State() {};
	virtual void OnDestory_State() {};
	//定时器更�?
	virtual void OnTimerUpdate(uint32_t nTimerID){};
	//执行事件
	virtual void OnExecuteEvent(uint16_t nEventID, uint32_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen){};
	//掉线
	virtual void OnDisconnect(Player *pPlayer) {};
protected:
	//副本ID
	uint32_t m_nDuplicateID;
	//副本配置
	const DuplicateDuplicateCfgInfo *m_pDuplicateCfg;
	//通关条件
	const VEC_INT32 *m_pVecCondition;
	//星级条件
	const VEC_VEC_INT32 *m_pMapStar;
	//副本你对应的场景
	Scene *m_pScene;
	//开始时�?
	uint64_t m_nStartTime;
	//开始刷怪时�?
	uint64_t m_nStartBrushTime;
	//副本准备状态开始时�?准备状态时间过长，需要自动销毁副�?
	uint64_t m_nReadyStartTime;
	//是否甩完所有�?
	bool m_bFinishBrush;
	//准备状态下是否超时
	bool m_bReadyTimeOut;
	//副本是否结束
	bool m_bEnd;
	//是否通知过中心服
	bool m_bNotifyEnd;
	//副本结果(副本结束了才有效)
	int32_t m_nResult;
	//场景玩家
	SET_UINT64 m_setPlayer;
	//场景怪物
	SET_UINT64 m_setMonster;
	//场景NPC
	SET_UINT64  m_setNpc;
	//机器�?
	SET_UINT64 m_setRobot;
	//杀怪数�?
	MAP_UINT64_UINT32 m_mapKillNum;
	//死亡次数
	MAP_UINT64_UINT32 m_mapDieNum;
	//复活次数
	MAP_UINT64_UINT32 m_mapReliveNum;
	//所有死亡怪物数量
	MAP_UINT32_UINT32 m_mapAllDieMonter;
	//所有的类型的怪
	MAP_INT8_MAP_UINT32_UINT32 m_mapAllTypeMonster;
	//所有的怪物 (记录副本中所有的怪物数量，供查询用，初始化之后，数量不允许变)
	MAP_UINT32_INT32 m_mapAllMonster;
	//玩家死亡复活
	MAP_UINT64_UINT64 m_mapPlayerRelive;
	//曾经进入过副本的玩家（针对再次上线进入副本的情况�?
	SET_UINT64 m_setOnceEnter;
	//玩家是否可获得奖�?
	SET_UINT64 m_setReward;
	//塔的cid
	CharIDType m_towerCid;
	//玩家输出伤害
	MAP_UINT64_UINT64 m_mapPlayerOuput;
	//玩家承受伤害
	MAP_UINT64_UINT64 m_mapPlayerBear;
	//角色上次生命
	MAP_UINT64_UINT32 m_mapPlayerLastHp;
	//副本功勋（塔防和守护)
	MAP_UINT64_INT32 m_mapExploit;
	//场景怪物组-怪物（主要用于制定怪物进入区域刷新） groupid - monsCid
	MAP_UINT32_SET_UINT64 m_mapGroupMons;
public:
	explicit Duplicate();
	virtual ~Duplicate();
protected:
	//副本类型
	int8_t m_byType;
	//场景ID
	uint32_t m_nSceneID;
	//地图ID
	uint32_t m_nMapID;
	//刷怪数�?
	AllBrushDataCfg m_brushCfg;
	//刷�?
	IBrushMonster *m_pBrushMonster;
	//条件
	ICond *m_pCond;
	//星级
	DupStar m_dupStar;
	//副本额外参数
	DExParam m_paramEx;
	//怪物剩余数量
	int32_t m_monsterNum;
	//出生的怪物
	SET_UINT64 m_setBornMonster;
	//副本阻挡
	DupBlock m_dupBlock;
	//阻挡配置
	AllBlockDataCfg m_blockCfg;
	//死亡复活时间 单位：秒
	int32_t m_reliveSec;
};